﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web;
using MC.RideEvent.Mvc.Helpers.Exceptions;
using MC.RideEvent.Mvc.Models.Entity;
using MC.RideEvent.Mvc.Models.ViewModel;
using AutoMapper;

namespace MC.RideEvent.Mvc.Models.Repository
{
    public class WayRepository : IWayRepository
    {
        private const int THE_LAST = 5;
        private RideEventDBEntities _context;

        public WayRepository()
        {
            _context = new RideEventDBEntities();
        }

        public Way GetWay(int id)
        {
            var way = from w in _context.Ways
                      join e in _context.Events on w.EventId equals e.Id
                      where e.DateBegin >= DateTime.Now
                      select w;

            var item = way.FirstOrDefault();

            return item;
        }

        public List<WayViewModel> GetWays()
        {
            var dateNow = DateTime.Now;
            var list = from w in _context.Ways
                       join e in _context.Events on w.EventId equals e.Id
                       where e.DateBegin >= DateTime.Now 
                       select new WayViewModel
                       {
                           CodeWay = w.CodeWay,
                           Contribution = w.Contribution,
                           EventId = w.EventId,
                           DriverId = w.DriverId,
                           MeetingHour = w.MeetingHour,
                           MeetingPlace = w.MeetingPlace,
                           Id = w.Id,
                           NumberPlaces = w.NumberPlaces,
                           City = e.City,
                           NamePlace = e.NamePlace,
                           DateEvent = e.DateBegin
                       };

            var result = list.ToList();

            return result;
        }

        public List<WayViewModel> GetLastWays()
        {
            var list = from w in _context.Ways
                       join e in _context.Events on w.EventId equals e.Id
                       where w.Event.DateBegin >= DateTime.Now
                       orderby w.Event.DateBegin descending
                       select new WayViewModel
                                  {
                                      CodeWay = w.CodeWay,
                                      Contribution = w.Contribution,
                                      EventId = w.EventId,
                                      DriverId = w.DriverId,
                                      MeetingHour = w.MeetingHour,
                                      MeetingPlace = w.MeetingPlace,
                                      Id = w.Id,
                                      NumberPlaces = w.NumberPlaces,
                                      City = e.City,
                                      NamePlace = e.NamePlace,
                                      DateEvent = e.DateBegin
                                  };

            var result = list.Take(THE_LAST).ToList();

            return result;
        }

        public WayViewModel GetWayById(int wayId)
        {
            var item = (from w in _context.Ways
                        //join e in _context.Events on w.EventId equals e.Id
                        where w.Id == wayId
                        select w).FirstOrDefault();
                       //select new WayViewModel
                       //{
                       //    CodeWay = w.CodeWay,
                       //    Contribution = w.Contribution,
                       //    EventId = w.EventId,
                       //    DriverId = w.DriverId,
                       //    MeetingHour = w.MeetingHour,
                       //    MeetingPlace = w.MeetingPlace,
                       //    Id = w.Id,
                       //    NumberPlaces = w.NumberPlaces,
                       //    City = e.City,
                       //    NamePlace = e.NamePlace,
                       //    DateEvent = e.DateBegin,
                       //}).FirstOrDefault();

            var data = Mapper.Map<Way, WayViewModel>(item);

            return data;
        }

        /// <summary>
        /// Recupere tous les trajets auxquelles l'utilisateur connecté
        /// a participé en tant que conducteur.
        /// </summary>
        /// <param name="driverId"></param>
        /// <returns></returns>
        public List<WayViewModel> GetWaysByDriverId(int driverId)
        {
            var dateNow = DateTime.Now;
            var list = (from w in _context.Ways
                        where w.DriverId == driverId
                        select w).ToList();

            var datas = Mapper.Map<List<Way>, List<WayViewModel>>(list);

            return datas;
        }

        /// <summary>
        /// Recupere tous les trajets auxquelles l'utilisateur connecté
        /// a participé en tant que passager.
        /// </summary>
        /// <param name="passagerId"></param>
        /// <returns></returns>
        public List<WayViewModel> GetWaysByPassagerId(int passagerId)
        {
            var dateNow = DateTime.Now;
            var list = (from pw in _context.PassagerWays
                        where pw.PassagerId == passagerId
                        select pw.Way).ToList();

            var datas = Mapper.Map<List<Way>, List<WayViewModel>>(list);

            return datas;
        }
        

        public List<WayViewModel> GetLastWaysByEventId(int eventId)
        {
            var list = from w in _context.Ways
                       where w.EventId == eventId
                       where w.Event.DateBegin >= DateTime.Now
                       orderby w.Event.DateBegin descending
                       select new WayViewModel
                       {
                           CodeWay = w.CodeWay,
                           EventId = w.EventId,
                           Contribution = w.Contribution,
                           DriverId = w.DriverId,
                           MeetingHour = w.MeetingHour,
                           MeetingPlace = w.MeetingPlace,
                           Id = w.Id
                       };

            var result = list.Take(THE_LAST).ToList();

            return result;
        }

        public List<WayViewModel> GetWaysByEventId(int eventId)
        {
            var list = (from w in _context.Ways
                       where w.EventId == eventId
                       where w.Event.DateBegin >= DateTime.Now
                       orderby w.Event.DateBegin descending
                       select w).ToList();

            var datas = Mapper.Map<List<Way>, List<WayViewModel>>(list);

            return datas;
        }

        public bool SaveWay(WayViewModel way, int userId, bool isUpdate)
        {
            Way w = null;

            if (isUpdate)
            {
                w = UpdateWay(way);
                _context.Entry(w);
                _context.Entry(w).State = EntityState.Modified;
            }
            else
            {
                w = CreateWay(way, userId);
                _context.Ways.Add(w);
            }

            var result = Convert.ToBoolean(_context.SaveChanges());

            return result;
        }

        public bool BecomePassager(int wayId, int memberId)
        {
            var pway = (from pw in _context.PassagerWays
                       where pw.WayId == wayId
                       where pw.PassagerId == memberId
                       select pw).FirstOrDefault();

            if(pway != null)
            {
                _context.PassagerWays.Add(pway);
            }

            var nb = _context.SaveChanges();

            return nb > 0;
        }

        private Way CreateWay(WayViewModel way, int memberId)
        {
            var dateNow = DateTime.Now;
            var w = AutoMapper.Mapper.Map<WayViewModel, Way>(way);
            w.CodeWay = Guid.NewGuid().ToString();
            w.DateCreation = dateNow;
            w.DateUpdate = dateNow;

            return w;
        }

        private Way UpdateWay(WayViewModel way)
        {
            var w = WayById(way.Id);

            if (w != null)
            {
                //check if the number place of vehicule is
                //smaller than the number places sized.
                var placeRemind = NumberPlacesReminding(w.NumberPlaces, way.NumberPlaces);

                if (placeRemind >= 0)
                {
                    w.NumberPlaces = placeRemind;
                }

                w.Contribution = way.Contribution;
                w.MeetingHour = way.MeetingHour;
                w.MeetingPlace = way.MeetingPlace;
                w.DateUpdate = DateTime.Now;
            }

            return w;
        }

        private Way WayById(int wayId)
        {
            var way = (from w in _context.Ways
                      where w.Id == wayId
                      select w).FirstOrDefault();

            return way;
        }

        private int NumberPlacesReminding(int placesInBase, int placeSized)
        {
            int result = 0;
            var remind = placesInBase - placeSized;

            if(remind >= 0)
            {
                result = remind;
            }
            else if(remind < 0)
            {
                throw new NumberPlaceOutOfBoundException();
            }

            return result;
        }

        private bool IfMemberIsPassager(int memberId, int way)
        {
            return false;
        }

        //ASUPP
        private WayViewModel SetUserOnWay(WayViewModel way)
        {
            var user = (from m in _context.Members
                        where m.Id == way.DriverId
                        select m).FirstOrDefault();

            var data = AutoMapper.Mapper.Map<Member, MemberViewModel>(user);

            way.Driver = data;

            return way;
        }
    }
}